package edu.ynu.se.xiecheng.achitectureclass.service;

import edu.ynu.se.xiecheng.achitectureclass.common.service.LogicService;
import edu.ynu.se.xiecheng.achitectureclass.dao.CameraDao;
import edu.ynu.se.xiecheng.achitectureclass.dto.CameraDTO;
import edu.ynu.se.xiecheng.achitectureclass.entity.Camera;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import javax.annotation.PostConstruct;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class CameraService extends LogicService<CameraDao, Camera, Long> {
    private String accessToken;
    private long tokenExpirationTime;
    
    // 定义摄像头列表
    private final String[] CAMERA_SERIALS = {
        "AB9831171",
        "AC0174303",
        "AB9831218",
        "L29334649"
    };

    public CameraService(@Autowired CameraDao cameraDao) {
        super(cameraDao);
        refreshToken();
    }

    // 应用启动时执行第一次抓拍
    @PostConstruct
    public void init() {
        System.out.println("应用启动，开始第一次抓拍...");
        captureAllCameras();
    }

    // 每10分钟执行一次自动抓拍
    @Scheduled(fixedRate = 600000) // 600000毫秒 = 10分钟
    public void scheduledCapture() {
        System.out.println("开始定时抓拍任务: " + new Date());
        captureAllCameras();
    }

    // 抓拍所有摄像头
    private void captureAllCameras() {
        for (String deviceSerial : CAMERA_SERIALS) {
            try {
                System.out.println("正在抓拍摄像头: " + deviceSerial);
                String picUrl = captureImage(deviceSerial, 1, 1); // 使用高清质量(quality=1)
                if (picUrl != null) {
                    System.out.println("摄像头 " + deviceSerial + " 抓拍成功: " + picUrl);
                } else {
                    System.out.println("摄像头 " + deviceSerial + " 抓拍失败");
                }
            } catch (Exception e) {
                System.err.println("摄像头 " + deviceSerial + " 抓拍出错: " + e.getMessage());
            }
        }
    }

    private void refreshToken() {
        String tokenUrl = "http://42.193.14.241:7000/ysapi/subAccount/getToken";
        String accountId = "1ca7f0ab24ba41b291346347ec30140e";

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        JSONObject requestBody = new JSONObject();
        requestBody.put("accountId", accountId);

        HttpEntity<String> entity = new HttpEntity<>(requestBody.toString(), headers);

        try {
            RestTemplate restTemplate = new RestTemplate();
            ResponseEntity<String> response = restTemplate.postForEntity(tokenUrl, entity, String.class);

            if (response.getStatusCode().is2xxSuccessful()) {
                JSONObject jsonResponse = new JSONObject(response.getBody());
                JSONObject data = jsonResponse.getJSONObject("data");
                accessToken = data.getString("accessToken");
                tokenExpirationTime = data.getLong("expireTime");
                System.out.println("Token refreshed successfully: " + accessToken);
            }
        } catch (Exception e) {
            System.err.println("Error refreshing token: " + e.getMessage());
        }
    }

    public String captureImage(String deviceSerial, Integer channelNo, Integer quality) {
        // 检查token是否过期
        if (System.currentTimeMillis() >= tokenExpirationTime) {
            refreshToken();
        }

        String captureUrl = "https://open.ys7.com/api/lapp/device/capture";
        
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
        requestBody.add("accessToken", accessToken);
        requestBody.add("deviceSerial", deviceSerial);
        requestBody.add("channelNo", String.valueOf(channelNo));
        if (quality != null) {
            requestBody.add("quality", String.valueOf(quality));
        }

        HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(requestBody, headers);

        try {
            RestTemplate restTemplate = new RestTemplate();
            ResponseEntity<String> response = restTemplate.postForEntity(captureUrl, entity, String.class);

            if (response.getStatusCode().is2xxSuccessful()) {
                JSONObject jsonResponse = new JSONObject(response.getBody());
                if ("200".equals(jsonResponse.getString("code"))) {
                    String picUrl = jsonResponse.getJSONObject("data").getString("picUrl");
                    
                    // 保存抓拍记录
                    Camera camera = new Camera();
                    camera.setDeviceSerial(deviceSerial);
                    camera.setPicUrl(picUrl);
                    camera.setCaptureTime(new Date());
                    camera.setChannelNo(channelNo);
                    camera.setQuality(quality);
                    getDAO().save(camera);
                    
                    return picUrl;
                }
            }
        } catch (Exception e) {
            System.err.println("Error capturing image: " + e.getMessage());
        }
        return null;
    }

    public List<CameraDTO> getLatestCaptures(String deviceSerial) {
        List<Camera> cameras = getDAO().findByDeviceSerialOrderByCaptureTimeDesc(deviceSerial);
        return cameras.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    private CameraDTO convertToDTO(Camera camera) {
        CameraDTO dto = new CameraDTO();
        dto.setId(camera.getId());
        dto.setDeviceSerial(camera.getDeviceSerial());
        dto.setPicUrl(camera.getPicUrl());
        dto.setCaptureTime(camera.getCaptureTime());
        dto.setChannelNo(camera.getChannelNo());
        dto.setQuality(camera.getQuality());
        return dto;
    }
} 